#include <ximera/system/application.hpp>
#include <ximera/logger.hpp>

#include <ximera/gui/ibutton.hpp>
#include <ximera/gui/icheckbox.hpp>
#include <ximera/gui/ilistbox.hpp>
#include <ximera/gui/icombobox.hpp>
#include <ximera/gui/iprogressbar.hpp>
#include <ximera/gui/islider.hpp>
#include <ximera/gui/ispinner.hpp>
#include <ximera/gui/itextbox.hpp>
#include <ximera/gui/iradiobutton.hpp>

#include <iostream>

using namespace ximera;

struct GuiTestHandler : ximera::system::AppHandler
{
    GuiTestHandler(system::Application& app)
        : application(app) {}

    virtual void onStart(system::AppEventArgs& event)
    {
        try
        {
            setupWorld();
            setupCamera();
            setupGui();
        }
        catch (ximera::Exception& e)
        {
            event.app.shouldClose(true);
            XIMERA_LOG() << e << std::endl;
        }
    }

private:
    system::Application& application;

    graphics::IWorldPtr graphicsWorld;
    graphics::ICameraPtr camera;
    graphics::IViewportPtr viewport;

    SharedPtr<gui::IWindow> rootWindow;
    SharedPtr<gui::IWindow> window;
    SharedPtr<gui::IButton> button;
    SharedPtr<gui::ICheckbox> check;
    SharedPtr<gui::IListbox> list;
    SharedPtr<gui::ICombobox> combo;
    SharedPtr<gui::IProgressBar> progress;
    SharedPtr<gui::ISlider> slider;
    SharedPtr<gui::ISpinner> spinner;
    SharedPtr<gui::ITextbox> text;

    void setupWorld()
    {
        graphicsWorld.reset(application.graphicsSystem()->createWorld());
        application.graphicsSystem()->ambientLight(math::Color(0.5f, 0.5f, 0.5f));
    }

    void setupCamera()
    {
        camera.reset(graphicsWorld->createCamera(L"default"));
        camera->position(math::Vector3(70, 20, -50));
        camera->lookAt(math::Vector3(0, 0, 0));

        viewport.reset(graphicsWorld->createViewport(camera.get()));
    }

    void setupGui()
    {
        application.guiSystem()->loadScheme(L"TaharezLookSkin.scheme");
        application.guiSystem()->mouseCursor(L"MouseArrow");

        rootWindow.reset(application.guiSystem()->createWindow(L"DefaultWindow", L"Sheet"));
        //rootWindow.reset(application.guiSystem()->createWindow(L"ogregui.layout"));        
        application.guiSystem()->activeWindow(rootWindow.get());

        window.reset(application.guiSystem()->createWindow(L"TaharezLook/FrameWindow", L"Test"));        
        window->size(.7f, .5f);
        rootWindow->addChild(window.get());

        button.reset(application.guiSystem()->createWindow<gui::IButton>(L"TaharezLook/Button", L"Button"));        
        button->text(L"Quit");
        button->position(0.1f, 0.15f);
        button->size(0.2f, 0.1f);
        button->onClick() += boost::bind(&GuiTestHandler::button_Click, this, _1);
        button->onMouseExit() += boost::bind(&GuiTestHandler::button_MouseExit, this, _1);
        button->onMouseEnter() += boost::bind(&GuiTestHandler::button_MouseEnter, this, _1);
        window->addChild(button.get());

        check.reset(application.guiSystem()->createWindow<gui::ICheckbox>(L"TaharezLook/Checkbox", L"Check"));        
        check->text(L"My option..");
        check->position(0.1f, 0.40f);
        check->size(0.2f, 0.1f);
        window->addChild(check.get());

        list.reset(application.guiSystem()->createWindow<gui::IListbox>(L"TaharezLook/Listbox", L"List"));
        list->position(0.5f, 0.10f);
        list->size(0.3f, 0.4f);
        list->addItem(L"item1");
        list->addItem(L"item2");
        list->addItem(L"item3");
        window->addChild(list.get());

        combo.reset(application.guiSystem()->createWindow<gui::ICombobox>(L"TaharezLook/Combobox", L"Combo"));
        combo->position(0.2f, 0.6f);
        combo->size(0.3f, 0.4f);
        combo->readOnly(true);
        combo->addItem(L"item1");
        combo->addItem(L"item2");
        combo->addItem(L"item3");
        window->addChild(combo.get());

        text.reset(application.guiSystem()->createWindow<gui::ITextbox>(L"TaharezLook/Editbox", L"Text"));
        text->text(L"Testing");
        text->position(0.2f, 0.75f);
        text->size(0.2f, 0.1f);
        window->addChild(text.get());

        progress.reset(application.guiSystem()->createWindow<gui::IProgressBar>(L"TaharezLook/ProgressBar", L"Progress"));
        progress->position(0.6f, 0.80f);
        progress->size(0.2f, 0.05f);
        progress->maxValue(30);
        progress->value(15);
        window->addChild(progress.get());

        slider.reset(application.guiSystem()->createWindow<gui::ISlider>(L"TaharezLook/Slider", L"Slider"));
        slider->text(L"Testing");
        slider->position(0.2f, 0.9f);
        slider->maxValue(10);        
        slider->size(0.2f, 0.02f);
        window->addChild(slider.get());
    }

    void button_Click(gui::GuiEventArgs& e)
    {
        application.shouldClose(true);
    }

    void button_MouseEnter(gui::GuiEventArgs& e)
    {
        text->text(L"Mouse Enter");
        combo->showDropDownList();
    }

    void button_MouseExit(gui::GuiEventArgs& e)
    {
        text->text(L"Mouse Exit");
        combo->hideDropDownList();
    }
};

int main()
{
    try
    {
        XIMERA_LOG().stream(&std::wcout);

        system::AppSettings settings;
        settings[L"ximera.plugins.input"] = XIMERA_PLUGIN(L"XimeraDInput8");
        settings[L"ximera.plugins.graphics"] = XIMERA_PLUGIN(L"XimeraOgre");
        settings[L"ximera.plugins.gui"] = XIMERA_PLUGIN(L"XimeraCEGui");
        settings[L"ximera.ogre.showdialog"] = L"1";

        system::Application app(settings);

        GuiTestHandler handler(app);
        app.addHandler(handler);

        return app.run();
    }
    catch (ximera::Exception& e)
    {
        XIMERA_LOG() << e << std::endl;
    }
}
